
var canvas;
var context;
var mapWidth, mapHeight;
var speed = 2;
var timeout = 17;
var srcPath = "";
var stateGame = {
    ready: 0,
    play: 1,
    gameOver: 2,
    die: 3,
}

window.onload = function() {
    init();
    gameLoop();
}

function gameLoop()
{
    var timeForward = Date.now();
    if (currentstate != stateGame.die) {
        updateGame();
        drawGame();
    }
    else
        drawMenu();
    var diffTime = Date.now() - timeForward;
    setTimeout(gameLoop, timeout - diffTime);
}

function init() {
    canvas = document.getElementById("myCanvas");
    context = canvas.getContext("2d");
    canvas.addEventListener("mousedown", function(evt) {
        jumpBird(evt);
        mouseEvent("mousedown", evt);
    }, false);
    canvas.addEventListener("mousemove", function(evt) {
        mouseEvent("mousemove", evt)
    }, false);
    canvas.addEventListener("mouseup", function(evt) {
        mouseEvent("mouseup", evt)
    }, false);
    document.onkeydown = function(evt) {
        if (evt.keyCode == 32)
            jumpBird(evt);
    };
    initGame();
    initSocket();
}
function sendScore() {
    //prepare json data  
    var tmp;
    if(userName != "No name") {
        var msg = {
            message: score,
            name: userName,
            type: 'score',
        };        
        //convert and send data to server
        websocket.send(JSON.stringify(msg));
    }
}

function initSocket() {
    //create a new WebSocket object.
    var wsUri = "ws://localhost:9000";
    websocket = new WebSocket(wsUri);
    websocket.onopen = function(ev) { // connection is open 

    }
    //#### Message received from server?
    websocket.onmessage = function(ev) {
        
    };

    websocket.onerror = function(ev) {
    };
    websocket.onclose = function(ev) {
    };
}
function mouseEvent(event, mouse) {
    if (currentstate == stateGame.die) {
        var mousePos = getMouse(mouse);
        checkButton(mousePos.x, mousePos.y, event);
    }
}
function getMouse(evt) {
    var rect = canvas.getBoundingClientRect();
    return{
        x: evt.clientX - rect.left,
        y: evt.clientY - rect.top
    }
}
function initGame() {
    mapWidth = canvas.width;
    mapHeight = canvas.height;
    background = new Image();
    var tmpSocre = document.getElementById("lbScore").innerHTML
    if(tmpSocre) scoreMax = tmpSocre;
    else scoreMax = 0;
    var tmp;
    if(tmp = document.getElementById("lbUser")) {
        userName = tmp.innerHTML;
    }
    else userName = "No name";
    background.src = srcPath + "ImagesGame/bg.jpg";
    bottomImage = new Image();
    bottomImage.src = srcPath + "ImagesGame/bottom.jpg";
    topImage = new Image();
    topImage.src = srcPath + "ImagesGame/top.jpg";
    scoreImage = new Image();
    scoreImage.src = srcPath + "ImagesGame/score.png";
    scoreImage.draw = function() {
        context.drawImage(scoreImage, 30, 50);
        context.save();
        context.fillStyle = "Black";
        context.font = "bold 32px arial";
        context.textAlign = "center";
        context.fillText("Score: " + score, 30 + scoreImage.width / 2, 50 + scoreImage.height / 2 + 16);
        context.restore();
    }
    menuImage = new Image();
    menuImage.src = srcPath + "ImagesGame/bgMenu.png";
    menuImage.draw = function() {
        context.drawImage(menuImage, mapWidth / 2 - menuImage.width / 2, mapHeight / 2 - menuImage.height / 2);
    }
    topImage.draw = function(_context) {
        _context.drawImage(topImage, coordinateX, 0);
        _context.drawImage(topImage, topImage.width + coordinateX, 0);
    };
    bottomImage.draw = function(_context) {
        _context.drawImage(bottomImage, coordinateX, mapHeight - bottomImage.height);
        _context.drawImage(bottomImage, bottomImage.width + coordinateX, mapHeight - bottomImage.height);
    }
    bird = new Bird({
        frameWidth: 70,
        frameHeight: 50,
        numFrame: 5,
        imgSrc: srcPath + "ImagesGame/bird.png",
    });
    pipeList = new PipeList({
        mapWidth: mapWidth,
        mapHeight: mapHeight,
        frameWidth: 100,
        startX: 1024,
        cyTop: 30,
        cyButtom: 80,
    });
    initSound();
    gameReady();
    initButton();
}
function initButton() {
    btPlayAgain = new Button({
        src: srcPath + "ImagesGame/btPlayAgain.png",
        x: mapWidth / 2 - 218,
        y: mapHeight / 2 + 45,
        context: context,
        value: "Play angain",
        sizeFont: 25,
    });
    btRank = new Button({
        src: srcPath + "ImagesGame/btPlayAgain.png",
        x: mapWidth / 2 + 30,
        y: mapHeight / 2 + 45,
        context: context,
        value: "View rank",
        sizeFont: 25,
    });
}
function gameOver() {
    currentstate = stateGame.gameOver;
    playSound(hitSound);
    speed = 0;
    pipeList.speedX = 0;
    bird.velocity = 0;
}
function gameReady() {
    collision = false;
    currentstate = stateGame.ready;
    score = 0;
    bird.gameReady();
    pipeList.gameReddy();
    coordinateX = 0;
    speed = 3;
    pipeList.speedX = speed;
}
function gamePlay() {
    currentstate = stateGame.play;
    bird.gamePlay();
}
function gameDie() {
    if (score > scoreMax) {
        scoreMax = score;
        sendScore();
    }
    currentstate = stateGame.die;
    playSound(dieSound);
}
function updateGame() {
    var birdFall = bird.cy + bird.frameWidth / 2;
    if (currentstate == stateGame.gameOver && birdFall >= 555)
        bird.cy++;
    else
        bird.update();
    if (currentstate == stateGame.play) {
        pipeList.update();
        checkScore();
    }
    collision = checkCollision(topImage, bottomImage, findIntersectionEdge()) || checkCollision(null, pipeList, findIntersectionPipe());
    if (collision && currentstate == stateGame.play)
        gameOver();
    coordinateX -= speed;
    if (coordinateX + bottomImage.width < 0)
        coordinateX = 0;
}
function clearScreen() {
    context.clearRect(0, 0, canvas.width, canvas.height);
}
function drawGame() {
    context.drawImage(background, 0, -80);
    topImage.draw(context);
    bottomImage.draw(context);
    if (currentstate != stateGame.ready) {
        pipeList.draw(context);
        scoreImage.draw();
    }
    else if (currentstate == stateGame.ready) {
        context.save();
        context.fillStyle = "black";
        context.font = "bold 36px arial";
        context.textAlign = "center";
        context.fillText("Press the space key or click the mouse to fly up", mapWidth / 2, mapHeight / 2 - 100);
        context.restore();
    }
    bird.draw(context);
}
function drawMenu() {
    menuImage.draw();
    btRank.draw();
    btPlayAgain.draw();
    context.save();
    context.fillStyle = "Red";
    context.font = "bold 26px arial";
    context.textAlign = "center";
    context.fillText("Score: " + score, mapWidth / 2, mapHeight / 2 - 70);
    context.fillText("Best score: " + scoreMax, mapWidth / 2, mapHeight / 2 - 30);
    context.fillText("User name: " + userName, mapWidth / 2, mapHeight / 2 + 10);
    context.restore();
}
function checkButton(x, y, evt) {
    btPlayAgain.checkStatus(x, y, evt);
    if (btPlayAgain.isClick) {
        btPlayAgain.reset();
        gameReady();
    }
    else {
        btRank.checkStatus(x, y, evt);
        if (btRank.isClick) {
            btRank.reset();
            viewRank();
        }
    }
}
function viewRank() {
    location.href = "rank.php";    
}
function initSound() {
    wingSound = new Audio(srcPath + "SoundsGame/wing.mp3");
    scoreSound = new Audio(srcPath + "SoundsGame/point.mp3");
    hitSound = new Audio(srcPath + "SoundsGame/hit.mp3");
    dieSound = new Audio(srcPath + "SoundsGame/die.mp3");
    swooshingSound = new Audio(srcPath + "SoundsGame/swooshing.mp3");
}
function checkScore() {
    for (var i = 0; i < pipeList.numPipe; i++)
        if (pipeList.list[i].cx + pipeList.frameWidth / 2 <= bird.cx && !pipeList.list[i].score) {
            playSound(scoreSound);
            pipeList.list[i].score = true;
            score++;
        }
}
function playSound(sound) {
    sound.currentTime = 0;
    sound.play();
}
function jumpBird(evt) {
    if (currentstate == stateGame.play) {
        playSound(wingSound);
        bird.jump();
    }
    else if (currentstate == stateGame.ready)
        gamePlay();
}
function checkCollision(entity1, entity2, findIntersection) {
    var rect = findIntersection;
    rect.left = Math.floor(rect.left);
    rect.top = Math.floor(rect.top);
    rect.right = Math.floor(rect.right);
    rect.bottom = Math.floor(rect.bottom);
    if (rect.left >= rect.right || rect.top >= rect.bottom)
        return;
    context.clearRect(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
    bird.draw(context);
    var data1 = context.getImageData(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top).data;
    context.clearRect(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
    if (entity1 != null)
        entity1.draw(context);
    if (entity2 != null)
        entity2.draw(context);
    var data2 = context.getImageData(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top).data;
    var len = data1.length;
    for (var i = 3; i < len; i += 100)
        if (data1[i] != 0 && data2[i] != 0) {
            if (rect.entityCollision == 3)
                gameDie();
            return true;
        }
    return false;
}
function findIntersectionPipe() {
    var radius = Math.sqrt(bird.frameWidth * bird.frameWidth + bird.frameHeight * bird.frameHeight);
    var birdLeft = bird.cx - radius / 2, birdTop = bird.cy - radius / 2;
    var minDistance = Math.abs(pipeList.list[0].cx - bird.cx), index = 0;
    for (var i = 1; i < pipeList.numPipe; i++)
    {
        var tmp = Math.abs(pipeList.list[i].cx - bird.cx);
        if (tmp < minDistance) {
            index = i;
            minDistance = tmp;
        }
    }
    var rect;
    if (Math.abs(30 + pipeList.list[index].heightTop - bird.cy) < Math.abs(560 - pipeList.list[index].heightButtom - bird.cy))
    {
        rect = {
            left: Math.max(birdLeft, pipeList.list[index].cx),
            top: Math.max(birdTop, 30),
            right: Math.min(birdLeft + radius, pipeList.list[index].cx + pipeList.frameWidth),
            bottom: Math.min(birdTop + radius, 30 + pipeList.list[index].heightTop),
            entityCollision: 0,
        };
    }

    else {
        rect = {
            left: Math.max(birdLeft, pipeList.list[index].cx),
            top: Math.max(birdTop, 560 - pipeList.list[index].heightButtom),
            right: Math.min(birdLeft + radius, pipeList.list[index].cx + pipeList.frameWidth),
            bottom: Math.min(birdTop + radius, 560),
            entityCollision: 1,
        };
    }
    return rect;
}
function findIntersectionEdge() {
    var radius = Math.sqrt(bird.frameWidth * bird.frameWidth + bird.frameHeight * bird.frameHeight);
    var birdLeft = bird.cx - radius / 2, birdTop = bird.cy - radius / 2;
    var rect;
    if (bird.cy <= canvas.height / 2)
    {
        rect = {
            left: Math.max(birdLeft, 0),
            top: Math.max(birdTop, 0),
            right: Math.min(birdLeft + radius, 1024),
            bottom: Math.min(birdTop + radius, topImage.height),
            entityCollision: 2,
        };
    }

    else {
        rect = {
            left: Math.max(birdLeft, 0),
            top: Math.max(birdTop, 640 - bottomImage.height),
            right: Math.min(birdLeft + radius, 1024),
            bottom: Math.min(birdTop + radius, 640),
            entityCollision: 3,
        };
    }
    return rect;
}